#include "StatusMessageDialog.h"
#include "../../core/Impp.h"
#include "../StdUserInterfaceModule/Icons.h"

namespace Impp
{
//*
BEGIN_EVENT_TABLE(StatusMessageDialog, wxFrame)
	EVT_BUTTON(wxID_OK, StatusMessageDialog::onOK)
	EVT_BUTTON(NEW_SAVE, StatusMessageDialog::onSaveAs)
	EVT_TREE_SEL_CHANGED(STATUS_TREE_ID, StatusMessageDialog::onSelectionChanged)
	EVT_TREE_ITEM_MENU(STATUS_TREE_ID, StatusMessageDialog::onContextMenu)
	EVT_TOOL(STATUS_TREE_ITEM_DELETE,StatusMessageDialog::onDeleteItem)
	EVT_TOOL_RANGE(ID_STATUS_ONLINE, ID_STATUS_OFFLINE, StatusMessageDialog::onStatusSelected)
	EVT_TOOL_RANGE(ID_STATUS_EXTENDED_START, ID_STATUS_EXTENDED_END, StatusMessageDialog::onExtendedStatusSelected)
END_EVENT_TABLE()
//*/
;

StatusMessageDialog::StatusMessageDialog(BuddyList* buddyList, db_id accountId)	:
	wxFrame(buddyList, wxID_ANY, _T("Status Message")),
	dontSaveOnSelectionChanged(false),
	curAccountId(accountId)
{
	SetSize(600,400);

	wxPanel* mainPane = new wxPanel(this,wxID_ANY);

	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	if(ui == NULL){
		wxLogError(wxT("StatusMessageDialog: No userinterface found, can not create StatusMessageDialog"));
	}

	statusTree = new wxTreeCtrl(mainPane,STATUS_TREE_ID,wxDefaultPosition,wxDefaultSize,wxTR_HIDE_ROOT|wxTR_FULL_ROW_HIGHLIGHT|wxTR_SINGLE|wxTR_DEFAULT_STYLE);
	statusTree->SetImageList(ui->getIcons()->getStatusImageList());

	rootID = statusTree->AddRoot(wxT("Status Messages"));

	StatusAndMsg* newSam = updateTreeForAccount(curAccountId);


	//StatusIcon
	statusIcon = new wxStaticBitmap(mainPane,ID_ICON_STATUS,ui->getIcons()->getStatusIcon(newSam->status));
	//StatusTxt
	statusTxt = new wxStaticText(mainPane,ID_TEXT_STATUS,statusToString(newSam->status));


	msgText = new wxTextCtrl(mainPane,wxID_ANY,wxEmptyString,wxDefaultPosition,wxDefaultSize,wxTE_MULTILINE);
	btOk = new wxButton(mainPane, wxID_OK, wxT("OK"));
	newSave = new wxButton(mainPane, NEW_SAVE, wxT("Save As"));

	if(statusTree->GetCount()==0){
		wxLogDebug(wxT("StatusMessageDialog::StatusMessageDialog: No Default Status Message! Check the Database setup"));
	}else{
		dontSaveOnSelectionChanged = true;
		statusTree->SelectItem(newStatusMsgId,true);
	}

	//Impp::exemplar()->getActiveAccounts(accounts);

	//wxString* array = new wxString[accounts.size() + 1];

	//array[0] = wxT("all");

	//std::vector<Account*>::iterator ia;
	//size_t i=1;
	//for(ia = accounts.begin(); ia != accounts.end(); ia++){
	//	Account* a = *ia;
	//	array[i] = wxString::Format(wxT("%s (%s)"), a->self->getCustomName().c_str(), a->self->getScreenName().c_str() );
	//	i++;
	//}

	//accountBox = new wxComboBox(mainPane,wxID_ANY,wxEmptyString,wxDefaultPosition,wxDefaultSize,accounts.size() +1 ,array, wxCB_DROPDOWN);
	//delete[] array;


	wxBoxSizer* mainSizer = new wxBoxSizer(wxHORIZONTAL);
	wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
	wxBoxSizer* buttonsSizer = new wxBoxSizer(wxHORIZONTAL);
	wxBoxSizer* statusIconSizer = new wxBoxSizer(wxHORIZONTAL);

	statusIconSizer->Add(statusIcon,0,wxSHAPED|wxTOP|wxRIGHT|wxBOTTOM,5);
	statusIconSizer->Add(statusTxt,0,wxSHAPED|wxTOP|wxRIGHT|wxBOTTOM,5);

	buttonsSizer->Add(newSave,0,wxSHAPED|wxALL,0);
	buttonsSizer->Add(btOk,0,wxSHAPED|wxLEFT,5);
	//buttonsSizer->Add(accountBox,0,wxSHAPED|wxLEFT,5);

	sizer->Add(statusIconSizer,0,wxSHAPED|wxTOP|wxRIGHT|wxBOTTOM,0);
	sizer->Add(msgText,1,wxEXPAND|wxRIGHT,0);
	sizer->Add(buttonsSizer,0,wxSHAPED|wxTOP|wxRIGHT,5);

	mainSizer->Add(statusTree,0,wxEXPAND|wxALL,5);
	mainSizer->Add(sizer,1,wxEXPAND|wxTOP|wxRIGHT|wxBOTTOM,5);
	mainPane->SetSizer(mainSizer);


    statusIcon->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(StatusMessageDialog::onStatusMouseDown),NULL, this);
    statusIcon->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusMessageDialog::onStatusMouseDown),NULL, this);
    statusTxt->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(StatusMessageDialog::onStatusMouseDown),NULL, this);
    statusTxt->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusMessageDialog::onStatusMouseDown),NULL, this);



	Layout();
	CenterOnParent();
	Show();
}

StatusMessageDialog::~StatusMessageDialog()
{
	for (std::vector<StatusAndMsg*>::iterator i(messages.begin()); i != messages.end(); ++i) {
		StatusAndMsg* cur = *i;
		delete cur;
	}
}

StatusAndMsg* StatusMessageDialog::updateTreeForAccount(db_id accountId){
	curAccountId=accountId;
	Impp::exemplar()->getDatabase()->getStatusMessages(messages, accountId);

	Status curStatus = Impp::exemplar()->getSelf(accountId)->getStatus();

	StatusAndMsg* newSam = NULL;

	for (std::vector<StatusAndMsg*>::iterator i(messages.begin()); i != messages.end(); ++i) {
		StatusAndMsg* cur = *i;
		if(cur->flags & STATUS_AND_MSG_FLAG_NEW){
			newSam = cur;
			newSam->status = curStatus;
		}
	}

	if(newSam == NULL){
		newSam = Impp::exemplar()->getDatabase()->createStatusMessage(accountId, curStatus, wxT("new"), wxEmptyString, STATUS_AND_MSG_FLAG_NEW);
		messages.push_back(newSam);
	}

	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	if(ui == NULL){
		wxLogError(wxT("StatusMessageDialog: No userinterface found, can not create StatusMessageDialog"));
	}

	for (std::vector<StatusAndMsg*>::iterator i(messages.begin()); i != messages.end(); ++i) {
		StatusAndMsg* cur = *i;
		wxTreeItemId id = statusTree->AppendItem(rootID,cur->title, ui->getIcons()->getStatusImageListId(cur->status));

		treeMap[id.m_pItem] = cur->id;

		if(cur->flags & STATUS_AND_MSG_FLAG_NEW){
			newStatusMsgId = id;
			wxLogDebug(wxT("with flag found"));
		}

	}

	return newSam;
}

void StatusMessageDialog::onOK(wxCommandEvent & event){
	Impp* impp = Impp::exemplar();

	StatusAndMsg* sam = getStatusAndMsgBy(statusTree->GetSelection());

	wxString newStatusMsg = msgText->GetValue();

	sam->msg = newStatusMsg;
	impp->getDatabase()->updateStatusMessage(sam);

	//int selected = accountBox->GetSelection();


	impp->setStatusAndChageState(curAccountId, sam->status,sam->msg, sam->status == INVISIBLE ? PRICACY_ALLOW_ONLY_PERMITLIST : PRICACY_BLOCK_ONLY_DENYLIST);

	/*
	if(selected != 0){
		Account* account = accounts[selected - 1];

	}else{
		std::vector<Account*>::iterator ia;
		for(ia = accounts.begin(); ia != accounts.end(); ia++){
			Account* a = *ia;
			impp->setStatusAndChageState(a->id, sam->status,sam->msg, sam->status == INVISIBLE ? ALLOW_ONLY_PERMITLIST : BLOCK_ONLY_DENYLIST);
		}
	}
	 */
	Hide();
	Destroy();
}

void StatusMessageDialog::onSaveAs(wxCommandEvent & event){
	StatusAndMsg* sam = getStatusAndMsgBy(statusTree->GetSelection());

	wxString msg = msgText->GetValue();
	wxString title = msg;

	if(title.Len() > 12){
		title = title.SubString(0,8) << wxT("...");
	}

	wxTextEntryDialog dialog(this, wxString(wxT("Enter a name for the Status Message:")), wxString(wxT("Name the Status Message")),title, wxOK | wxCANCEL);



    if (dialog.ShowModal() == wxID_OK)
    {
    	sam = Impp::exemplar()->getDatabase()->createStatusMessage(curAccountId, sam->status, dialog.GetValue(), msg,0);
    	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
    	wxASSERT(ui != NULL);
		wxTreeItemId id = statusTree->AppendItem(rootID,sam->title,ui->getIcons()->getStatusImageListId(sam->status));
		treeMap[id.m_pItem] = sam->id;
		messages.push_back(sam);
		dontSaveOnSelectionChanged = true;
		statusTree->SelectItem(id,true);

    }

}

StatusAndMsg* StatusMessageDialog::getStatusAndMsgBy(wxTreeItemId id){
	std::map<wxTreeItemIdValue,db_id>::iterator iter = treeMap.find(id.m_pItem);

	if( iter != treeMap.end() ) {
		db_id dbId = iter->second;

		for (std::vector<StatusAndMsg*>::iterator i(messages.begin()); i != messages.end(); ++i) {
			if(dbId == (*i)->id){
				return *i;
			}
		}

	}

	return NULL;
}

void StatusMessageDialog::onSelectionChanged(wxTreeEvent & event){
	wxTreeItemId oldId = event.GetOldItem().m_pItem;
	wxTreeItemId newId = event.GetItem().m_pItem;


    StatusAndMsg* newSam = getStatusAndMsgBy(newId);

	if(!dontSaveOnSelectionChanged){
		StatusAndMsg* oldSam = getStatusAndMsgBy(oldId);
		if(oldSam != NULL){ //check if oldSam still exsists
			oldSam->msg = msgText->GetValue();
			Impp::exemplar()->getDatabase()->updateStatusMessage(oldSam);
		}
	}
	dontSaveOnSelectionChanged=false;

	if(newSam!=NULL){
		msgText->SetValue(newSam->msg);
    	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
    	wxASSERT(ui != NULL);
		statusIcon->SetBitmap(ui->getIcons()->getStatusIcon(newSam->status));
		statusTxt->SetLabel(statusToString(newSam->status));
	}else{
		//was deleted, so change selection to default one:
		statusTree->SelectItem(newStatusMsgId,true);
	}

	//wxLogDebug(wxT("selected id: %s"),sam.id.ToString().c_str());
}

void StatusMessageDialog::onContextMenu(wxTreeEvent & event){
    wxMenu menu;
    menu.Append(STATUS_TREE_ITEM_DELETE, wxT("Delete"));
    PopupMenu(&menu);
}

void StatusMessageDialog::onDeleteItem(wxCommandEvent & event){
	wxTreeItemId id = statusTree->GetSelection().m_pItem;


	if(id != newStatusMsgId){
		statusTree->Delete(statusTree->GetSelection());
		StatusAndMsg* sam = getStatusAndMsgBy(id);

		if(sam!=NULL){
			//wxLogDebug(wxT("delete id: %s"),sam.id.ToString().c_str());
			Impp::exemplar()->getDatabase()->deleteStatusMessage(sam);
			std::map<wxTreeItemIdValue,db_id>::iterator iter =treeMap.find(id.m_pItem);
			if( iter != treeMap.end() ) {
				treeMap.erase(iter);
			}
		}else{
			wxLogError(wxT("StatusMessageDialog::onDeleteItem: Can not Delete Message, Message not found!"));
		}
	}else{
		StatusAndMsg* sam = getStatusAndMsgBy(newStatusMsgId);
		sam->msg=wxEmptyString;
		sam->status=ONLINE;
		Impp::exemplar()->getDatabase()->updateStatusMessage(sam);
		msgText->SetValue(wxEmptyString);
    	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
    	wxASSERT(ui != NULL);
		statusIcon->SetBitmap(ui->getIcons()->getStatusIcon(ONLINE));
		statusTxt->SetLabel(statusToString(ONLINE));
		dontSaveOnSelectionChanged = true;
		statusTree->SelectItem(newStatusMsgId, true);

	}
}

void StatusMessageDialog::onStatusMouseDown(wxMouseEvent& event){
	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	if(ui != NULL){
		wxTreeItemId id = statusTree->GetSelection().m_pItem;
		StatusAndMsg* sam = getStatusAndMsgBy(id);
		wxPoint pos = event.GetPosition();
		wxMenu menu;
		ui->buildChooseStatusMenu(&menu, Impp::exemplar()->getAccount(curAccountId), sam->status == INVISIBLE);

	    PopupMenu(&menu);
	}else{
		wxLogError(wxT("StatusMessageDialog::onStatusMouseDown: Coudn't build Status Menu, no Userinterface loaded!"));
	}
}

void StatusMessageDialog::onStatusSelected(wxCommandEvent & event){

	wxTreeItemId id = statusTree->GetSelection().m_pItem;
	StatusAndMsg* sam = getStatusAndMsgBy(id);

	Status status = UNKNOWN;
	PrivacySetting privacy = PRICACY_INVALID;

	switch (event.GetId()) {
		case ID_STATUS_ONLINE:
			status = ONLINE;
			break;
		case ID_STATUS_FREE4CHAT:
			status = FREE4CHAT;
			break;
		case ID_STATUS_AWAY:
			status =AWAY;
			break;
		case ID_STATUS_OCCUPIED:
			status = OCCUPIED;
			break;
		case ID_STATUS_DND:
			status = DND;
			break;
		case ID_STATUS_NA:
			status = NA;
			break;
		case ID_STATUS_OFFLINE:
			status = OFFLINE;
			break;
		case ID_STATUS_VISIBLE:
			privacy = PRICACY_BLOCK_ONLY_DENYLIST;
			break;
		case ID_STATUS_INVISIBLE:
			privacy = PRICACY_ALLOW_ONLY_PERMITLIST;
			break;
		default:
			break;
	}

	//handle status change:
	if(privacy == PRICACY_INVALID){
		//just status was changed so handle it:
		int xstatus = sam->status.getExtraStatus();
		status.setExtraStatus(xstatus);

		if(sam->status == INVISIBLE){
			status.setFlag(INVISIBLE);
		}

	}else{
		//handle visibility
		status = sam->status;

		if(privacy == PRICACY_BLOCK_ONLY_DENYLIST){
			status.clearFlag(INVISIBLE);
		}else{
			status.setFlag(INVISIBLE);
		}
	}

	sam->status=status;
	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	wxASSERT(ui != NULL);
	statusIcon->SetBitmap(ui->getIcons()->getStatusIcon(status));
	statusTxt->SetLabel(statusToString(status));

}

void StatusMessageDialog::onExtendedStatusSelected(wxCommandEvent & event){

	wxTreeItemId id = statusTree->GetSelection().m_pItem;
	StatusAndMsg* sam = getStatusAndMsgBy(id);

	int xstatus = event.GetId() -ID_STATUS_EXTENDED_START;


	sam->status.setExtraStatus(xstatus);
	iUserInterface* ui = Impp::exemplar()->getModuleManager()->getUserInterfaceModule();
	wxASSERT(ui != NULL);
	statusIcon->SetBitmap(ui->getIcons()->getStatusIcon(sam->status));

}

}
